package WebGamble;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.awt.BorderLayout;
import javax.swing.JPanel;

public class PCEggsTest extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	static String BaseURL = "http://www.pceggs.com/play/pg28Insert.aspx?LID=";
	static Random rand = new Random();

	static private HttpResponse httpResponse;
	static private DefaultHttpClient httpClient = new DefaultHttpClient();
	static public class showImg extends JPanel {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		JLabel jl = null;
		ImageIcon img = null;

		public showImg(InputStream bmpFile) throws IOException {
			img = new ImageIcon(ImageIO.read(bmpFile));
			jl = new JLabel(img);
			this.setLayout(new BorderLayout());
			this.add(jl, BorderLayout.CENTER);
		}
	}
	
	static public int GCD(int numA, int numB) {
		int gcd = 1;
		for (int k = 1; k <= numA && k <= numB; k++)
			if (numA % k == 0 && numB % k == 0)
				gcd = k;
		return gcd;
	}
	
	static public double min(double[] valList) {
		double val;
		val = valList[0];
		for(double value : valList) {
			if(value < val)
				val = value;
		}
		return val;
	}
	
	static public double max(double[] valList) {
		double val;
		val = valList[0];
		for(double value : valList) {
			if(value > val)
				val = value;
		}
		return val;
	}
	
	static public int sum(int[] valList) {
		int val = 0;
		for(int value : valList)
			val += value;
		return val;
	}
	static public double sum(double[] valList) {
		double val = 0;
		for(double value : valList)
			val += value;
		return val;
	}
	
	static public double score1(double[] oddsList, int[] distribution) {
		double[] score = new double[28];
		double count = 0;
		double s = sum(distribution);
		for(int i = 0; i < 28; i++) {
			score[i] = oddsList[i] * distribution[i] - s;
			if(score[i] < 0)
				count += baseDist[i];
		}
		return min(score) - count * 6;
	}
	static public int[] originDist = {1, 3, 6, 10, 15, 21, 28, 72, 90, 110, 126, 138, 146, 150, 150, 146, 128, 126, 110, 90, 72, 28, 21, 15, 10, 6, 3, 1};
	static public double total = sum(originDist);
	static public double score2(double[] oddsList, int[] distribution) {
		double[] score = new double[28];
		double count = 0;
		double s = sum(distribution);
		for(int i = 0; i < 28; i++) {
			score[i] = (oddsList[i] * distribution[i] - s) * originDist[i];
			if(score[i] < 0)
				count += baseDist[i];
		}
		return sum(score) / total - count * 15;
	}
	static public double score3(double[] oddsList, int[] distribution) {
		double[] score = new double[28];
		double s = sum(distribution);
		for(int i = 0; i < 28; i++) {
			score[i] = (oddsList[i] * distribution[i] - s) * originDist[i];
		}
		return sum(score) / total;
	}
	
	static public int[] baseDist = {1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
	
	static public int[] getNextDist(int[] distribution) {
		int[] nextDist = distribution.clone();
		while(true) {
			int i = rand.nextInt(16) + 6;
			int step = 1;
			double flag = rand.nextDouble();
			if(flag < 0.5)
				step = -1;
			int temp = nextDist[i] + step; 
			if(temp >= baseDist[i]) {
				nextDist[i] = temp;
				break;
			}
		}
		return nextDist;
	}
	static public int[] getNextDist0(int[] distribution) {
		int[] nextDist = distribution.clone();
		while(true) {
			int i = rand.nextInt(28);
			int step = 1;
			int temp = nextDist[i] + step; 
			if(temp >= baseDist[i]) {
				nextDist[i] = temp;
				break;
			}
		}
		return nextDist;
	}
	
	static public int showStatus(double[] oddsList, int[] distribution, int idx, boolean showFlag) {
		double[] score = new double[28];
		int s = sum(distribution);
		int count = 0;
		if(showFlag) {
			System.out.println(idx + "th step:");
			for(int i = 0; i < 28; i++) {
				System.out.printf("%d: %03d, ", i, distribution[i]);
			}
			System.out.println();
		}
		for(int i = 0; i < 28; i++) {
			score[i] = oddsList[i] * distribution[i] - s;
			if(score[i] < 0)
				count++;
			if(showFlag)
				System.out.printf("%d: %06f, ", i, score[i]);
		}
		if(showFlag) {
			System.out.println();
			System.out.println("Total negative: " + count);
			System.out.println("Min: " + min(score));
			System.out.println("Max: " + max(score));
			for(int i = 0; i < 28; i++)
				score[i] = score[i] * originDist[i];
			System.out.println("Avg: " + sum(score) / total);
			System.out.println("Num: " + s);
		}
		return count;
	}
	
	@SuppressWarnings("deprecation")
	public static void main(String[] args) throws ClientProtocolException, IOException, InterruptedException {
		HttpGet httpGet;
        httpGet = new HttpGet("http://www.pceggs.com/nologin.aspx");
		httpResponse = httpClient.execute(httpGet);
		String loginHtml = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
		httpGet.releaseConnection();
		
		httpGet = new HttpGet("http://www.pceggs.com/VerifyCode_Login.aspx?id=0." + Math.abs(rand.nextLong()));
        httpResponse = httpClient.execute(httpGet);
        JFrame pane = new JFrame("Image Pane");
        pane.getContentPane().add(new showImg(httpResponse.getEntity().getContent()));
        pane.pack();
        pane.setVisible(true);
        httpGet.releaseConnection();
        System.out.println("������֤�룺");
        String VerifyCode;
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        VerifyCode = reader.readLine();
		
		Document loginDoc = Jsoup.parse(loginHtml);
		String loginURL = "http://www.pceggs.com/nologin.aspx";
		Elements loginInputs = loginDoc.select("input");
        HttpPost httpPost = new HttpPost(loginURL);
        List <NameValuePair> params = new ArrayList <NameValuePair>();
		for(Element input : loginInputs) {
			if(input.attr("type").compareToIgnoreCase("password") == 0) {
				input.attr("name", "txt_PWD");
				input.val("qazxcdews123321");
			}
			else if(input.attr("name").compareToIgnoreCase("email") == 0) {
				input.attr("name", "txt_UserName");
				input.val("365064421@qq.com");
			}
			else if(input.attr("name").compareToIgnoreCase("txt_VerifyCode") == 0) {
				input.val(VerifyCode);
			}
			else if(input.attr("name").compareToIgnoreCase("FromUrl") == 0) {
				input.val("http://www.pceggs.com/play/pc28.aspx");
			}
			else if(input.attr("name").compareToIgnoreCase("Login_Submit") == 0) {
				input.attr("name", "Login_Submit.x");
				input.val("32");
				params.add(new BasicNameValuePair(input.attr("name"), input.val()));
				System.out.println(input.attr("name") + ": " + input.val());
				input.attr("name", "Login_Submit.y");
				input.val("8");
				params.add(new BasicNameValuePair(input.attr("name"), input.val()));
				System.out.println(input.attr("name") + ": " + input.val());
				continue;
			}
			
			params.add(new BasicNameValuePair(input.attr("name"), input.val()));
			System.out.println(input.attr("name") + ": " + input.val());
		}
        httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
        httpResponse = httpClient.execute(httpPost);
        if(httpResponse.getStatusLine().getStatusCode() == 302) {
        	System.out.println("��¼�ɹ���������");
        }
        loginHtml = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
        //System.out.println(loginHtml);
        //httpPost.releaseConnection();
        pane.dispose();
        
//        httpGet = new HttpGet("http://wap.pceggs.com/play/pc28.aspx");
//        httpResponse = httpClient.execute(httpGet);
//        String html = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
//        httpGet.releaseConnection();
//        Document document = Jsoup.parse(html);
//        Elements elements = document.select("li.kj_white_line:eq(5) a");
//        String gambleURL = elements.attr("href");
//        httpGet = new HttpGet(gambleURL);
//        httpResponse = httpClient.execute(httpGet);
//        html = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
//        httpGet.releaseConnection();
        
        //while(true) {
            httpGet = new HttpGet("http://www.pceggs.com/play/pc28.aspx");
            httpResponse = httpClient.execute(httpGet);
            String html = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");

            //httpGet.releaseConnection();
            Document document = Jsoup.parse(html);
            Elements elements = document.select("#panel tr:eq(5) td:eq(0)");
            int lid = Integer.parseInt(elements.get(0).text()) + 9088;
            String gambleURL = BaseURL + lid;
            int i;
            double[] oddsList = new double[28];
            String odds;
            //int[] distribution = {1, 1, 1, 1, 1, 1, 2, 5, 5, 5, 25, 25, 25, 25, 25, 25, 25, 25, 5, 5, 5, 2, 1, 1, 1, 1, 1, 1};
            int[] distribution = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
//            httpGet = new HttpGet("http://www.pceggs.com/play/pg28mode.aspx?refresh=" + (lid - 1));
//            httpGet.addHeader("X_REQUESTED_WITH", "XMLHttpRequest");
//            httpGet.addHeader("Referer", gambleURL);
//            httpResponse = httpClient.execute(httpGet);
//            odds = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
//            
//            
//            i = 0;
//            for(String value : odds.split(",")) {
//            	oddsList[i] = Double.parseDouble(value);
//            	i++;
//            }
//            httpGet.releaseConnection();
//            System.out.println();
        	
        	httpGet = new HttpGet("http://www.pceggs.com/play/pc28.aspx");
            httpResponse = httpClient.execute(httpGet);
            html = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
            httpGet.releaseConnection();
            document = Jsoup.parse(html);
            elements = document.select(".infro span:eq(3)");
            int money = Integer.parseInt(elements.text().replaceAll(",", ""));
            System.out.println("Current Money: " + money);
            Pattern p = Pattern.compile("GetRTime\\([0-9]+\\);"), p1 = Pattern.compile("[0-9]+");
            Matcher m = p.matcher(html);
            m.find();
            html = m.group();
            m = p1.matcher(html);
            m.find();
            int timeout = Integer.parseInt(m.group());
            if(timeout <= 2) {
            	System.out.println("��ʱ�˳�������");
            	System.exit(0);
            	//Thread.sleep(5000);
            	//continue;
            }
            
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            //Thread.currentThread();
    		//Thread.sleep((timeout - 2) * 1000);

    		long startT = System.currentTimeMillis(), endT;
            httpGet = new HttpGet("http://www.pceggs.com/play/pg28mode.aspx?refresh=" + (lid - 1));
            httpGet.addHeader("X_REQUESTED_WITH", "XMLHttpRequest");
            httpGet.addHeader("Referer", gambleURL);
            httpResponse = httpClient.execute(httpGet);
            odds = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
            i = 0;
            for(String value : odds.split(",")) {
            	oddsList[i] = Double.parseDouble(value);
            	System.out.print(oddsList[i] + ", ");
            	i++;
            }
            httpGet.releaseConnection();
            System.out.println();
//            double[] gambleNum = new double[28];
//            for(i = 0; i < 28; i++) {
//            	gambleNum[i] = distribution[i] * oddsList[i];
//            }
//            System.out.print("min: ");
//            System.out.println(min(gambleNum) - sum(distribution));
//            System.out.print("max: ");
//            System.out.println(max(gambleNum) - sum(distribution));
            //����ģ���˻�
            /*
             *  J(y)����״̬yʱ�����ۺ���ֵ
             *  Y(i)����ʾ��ǰ״̬
             *  Y(i+1)����ʾ�µ�״̬
             *  r�� ���ڿ��ƽ��µĿ���
             *  T�� ϵͳ���¶ȣ�ϵͳ��ʼӦ��Ҫ����һ�����µ�״̬
             *  T_min ���¶ȵ����ޣ����¶�T�ﵽT_min����ֹͣ����
            */
            double T, dE, r;
            T = sum(oddsList) * sum(distribution);
            r = 0.98;
            int[] nextDist;
            int score = showStatus(oddsList, distribution, i, true), nextScore = 0;
            int countFlag = 0;
            while (countFlag < 50 || i < 5000) {
    			nextDist = getNextDist(distribution);
    			dE = score2(oddsList, nextDist) - score2(oddsList, distribution);
    			nextScore = showStatus(oddsList, distribution, i, false);
    			if (dE > 0 && nextScore <= score) {
    				// ����ƶ���õ����Ž⣬�����ǽ����ƶ�
    				distribution = nextDist.clone(); // ���ܴ�Y(i)��Y(i+1)���ƶ�
    			}
    			else {
    				// ����exp( dE/T )��ȡֵ��Χ��(0,1) ��dE/TԽ����exp( dE/T )Ҳ
    				if (Math.exp(dE / T) > rand.nextDouble() * 7)
    					distribution = nextDist.clone(); // ���ܴ�Y(i)��Y(i+1)���ƶ�
    			}
    			T = r * T;
    			// �����˻� ��0<r<1 ��rԽ�󣬽���Խ��rԽС������Խ��
    			// ��r�����������ȫ�����Ž�Ŀ��ܻ�ϸߣ��������Ĺ��Ҳ�ͽϳ�����r��С���������Ĺ�̻�ܿ죬�����տ��ܻ�ﵽһ���ֲ�����ֵ
    			i++;
    			
    			
    			if(nextScore == score)
    				countFlag++;
    			else
    				countFlag = 0;
    			score = nextScore;
    		}
            
//            httpPost = new HttpPost("http://www.pceggs.com/play/pg28InsertDo.aspx");
//            List <NameValuePair> gambleParams = new ArrayList <NameValuePair>();
//            String temps = String.valueOf(distribution[0]);
//            int s = distribution[0];
//            for(i = 1; i < 28; i++) {
//            	temps = temps + "," + distribution[i];
//            	gambleParams.add(new BasicNameValuePair("SMONEY", String.valueOf(distribution[i])));
//            	s += distribution[i];
//            }
//            gambleParams.add(new BasicNameValuePair("ALLSMONEY", temps));
//            Date date = new Date();
//    		date.setMinutes((date.getMinutes() / 5 + 1) * 5);
//    		gambleParams.add(new BasicNameValuePair("CTIME", df.format(date)));
//    		gambleParams.add(new BasicNameValuePair("Cheat", "CAE"));
//    		gambleParams.add(new BasicNameValuePair("LID", String.valueOf(lid)));
//    		gambleParams.add(new BasicNameValuePair("SMONEYSUM", String.valueOf(s)));
//    		gambleParams.add(new BasicNameValuePair("SMONEYY", "ALD"));
//    		gambleParams.add(new BasicNameValuePair("_issue", String.valueOf(lid - 9088)));
//    		gambleParams.add(new BasicNameValuePair("isdb_p", "0"));
//    		gambleParams.add(new BasicNameValuePair("lastgain", ""));
//    		for(i = 0; i < gambleParams.size(); i++) {
//    			System.out.println(gambleParams.get(i).getName() + ": " + gambleParams.get(i).getValue());
//    		}
//    		httpPost.setEntity(new UrlEncodedFormEntity(gambleParams, HTTP.UTF_8));
//    		httpPost.addHeader("Host", "www.pceggs.com");
//    		httpPost.addHeader("Referer", gambleURL);
//    		httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:18.0) Gecko/20100101 Firefox/18.0");
    		
//            httpResponse = httpClient.execute(httpPost);
//            html = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
//            httpPost.releaseConnection();
            
            endT = System.currentTimeMillis();
            System.out.println();
            System.out.println("Running time: " + (endT - startT) / 1000 + "s");
            showStatus(oddsList, distribution, i, true);
            //Thread.sleep(50000);
        //}
        
	}
}